home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / ingres04.lzh / source / ovqp / interp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-05-30  |  15.2 KB  |  792 lines

  1. # include    <ingres.h>
  2. # include    <aux.h>
  3. # include    <symbol.h>
  4. # include    <tree.h>
  5. # include    <access.h>
  6. # include    "../decomp/globs.h"
  7. # include    <sccs.h>
  8. # include    <errors.h>
  9.  
  10. SCCSID(@(#)interp.c    8.6    5/30/88)
  11.  
  12.  
  13.  
  14. /*
  15. **
  16. ** INTERPRET
  17. **
  18. **     Processes the retrieved tuple from the De.ov_source relation
  19. **     according to the symbols in the list.  Recognition
  20. **     of characteristic delimiters and separators initiates
  21. **     action appropriate to a target list or qualification list
  22. **     as the case may be.
  23. **    
  24. **     Between delimiters, the symbol list is expected to be in
  25. **     Polish postfix form.  A qualification list is further
  26. **     expected to be in conjunctive normal form, with Boolean
  27. **     operators infixed.
  28. **
  29. */
  30.  
  31.  
  32. double    pow();
  33. double    sqrt();
  34. double    log();
  35. double    exp();
  36. double    sin();
  37. double    cos();
  38. double    atan();
  39.  
  40. # define SPUSH(v)    (++((struct stacksym *) v))
  41. # define SPOP(v)    (((struct stacksym *) v)--)
  42.  
  43. SYMBOL *
  44. interpret(istlist,list)
  45. int     istlist; /* signals a target list: used for string substitution */
  46. SYMBOL    **list;    /* ptr to list of sym pointers */
  47. {
  48.     register SYMBOL        *tos;
  49.     SYMBOL            *op1,*op2;    /*operands popped off stack*/
  50.     register ANYTYPE    *val1,*val2;    /*ptrs to values of operands*/
  51.     int            opval, optype, l1;
  52.     char            *s1;
  53.     int            byflag;
  54.     long            hitid;
  55.     extern char        *Usercode;
  56.     extern            ov_err();
  57.     int            cb_mark;
  58.     extern char        *ov_ovqpbuf;
  59.     extern char        *locv();
  60.     int            i;
  61.  
  62. #    ifdef xOTR1
  63.     if (tTf(72, 0))
  64.     {
  65.         printf("INTERP:  list=%x\n",list);
  66.         printf("         istlist = %d\n", istlist);
  67.     }
  68. #    endif
  69.  
  70.  
  71.     byflag = (list == De.ov_bylist);    /* set byflag if aggregate function */
  72.     tos = (SYMBOL *)(De.ov_stack-1);
  73.     /* reset the concat and ascii operator buffer */
  74.     seterr(De.ov_ovqpbuf, CBUFULL, ov_err);
  75.     cb_mark = markbuf(De.ov_ovqpbuf);
  76.  
  77. loop:
  78. #    ifdef xOTR1
  79.     if (tTf(72, 1) && tos >= (SYMBOL *) De.ov_stack)
  80.     {
  81.         printf("\ttops of stack=");
  82.         prstack(tos);    /* print top of stack element */
  83.     }
  84. #    endif
  85.     /* check for stack overflow */
  86.     l1 = getsymbol(SPUSH(tos), &list);     /* getsymbol changes the value of list */
  87.  
  88.     if (l1)
  89.     {
  90.  
  91.         freebuf(De.ov_ovqpbuf, cb_mark);
  92.         return (tos);
  93.     }
  94.     optype = tos->type;
  95.     opval = tos->value.sym_data.i2type;
  96.     op1 = tos;
  97.     SPOP(tos);        /* assume that stack will be popped */
  98.  
  99.     switch(optype)
  100.     {
  101.       case CHAR:
  102.                     /* do any chars have to be inserted? */
  103.         if (istlist && (Patnum || Globnum))
  104.         {
  105.             insert_chars(op1);
  106.         }
  107.       case INT:
  108.       case FLOAT:
  109.         SPUSH(tos);        /* just leave symbol on stack */
  110.         goto loop;
  111.  
  112.       case COP:
  113.         SPUSH(tos);        /* new symbol goes on stack */
  114.         tos->type = CHAR;
  115.         switch (opval)
  116.         {
  117.  
  118.           case opDBA:
  119.             tos->value.sym_data.cptype = Admin.adhdr.adowner;
  120.             tos->len = 2;
  121.             goto loop;
  122.  
  123.           case opUSERCODE:
  124.             tos->value.sym_data.cptype = Usercode;
  125.             tos->len = 2;
  126.             goto loop;
  127.         }
  128.  
  129.       case AND:        /* if top value false return immediately */
  130.         if (!tos->value.sym_data.i2type)
  131.         {
  132.             freebuf(De.ov_ovqpbuf, cb_mark);
  133.             return(tos);
  134.         }
  135.         else
  136.             SPOP(tos);
  137.         freebuf(De.ov_ovqpbuf, cb_mark);
  138.         goto loop;
  139.  
  140.       case OR:        /* if top value is true then skip to
  141.                 ** end of disjunction. */
  142.         if (tos->value.sym_data.i2type)
  143.         {
  144.             SPUSH(tos);
  145.             do
  146.             {
  147.                 getsymbol(tos, &list);     /* getsymbol changes the value of list */
  148.             } while (tos->type != AND);
  149.             optype = AND;
  150.             SPOP(tos);
  151.         }
  152.         SPOP(tos);
  153.         goto loop;
  154.  
  155.       case RESDOM:
  156.         freebuf(De.ov_ovqpbuf, cb_mark); /* init the concat and ascii buffer */
  157.         if (De.ov_result)
  158.         {
  159.             if (opval)    /* if gt zero then opval represents a real domain */
  160.             {
  161.                 if (byflag)
  162.                     opval++;    /* skip over count field for ag functs */
  163.                 rcvt(tos, De.ov_result->relfrmt[opval], De.ov_result->relfrml[opval]);
  164.                 tout(tos, De.ov_outtup+De.ov_result->reloff[opval], De.ov_result->relfrml[opval]);
  165.             }
  166.             else    /* opval refers to the tid and this is an update */
  167.             {
  168.                 De.ov_uptid = tos->value.sym_data.i4type;    /* copy tid */
  169.                 if (De.de_qmode == mdREPL || (De.ov_diffrel && De.de_qmode == mdDEL && De.ov_result->reldum.relindxd > 0 ))
  170.                 {
  171.                     /* De.ov_origtup must be left with the orig
  172.                     ** unaltered tuple, and De.ov_outtup must
  173.                     ** be initialized with the orig tuple.
  174.                     **
  175.                     ** De.ov_outtup only matters with REPL.
  176.                     ** Scan() sets up De.ov_origtup so when
  177.                     ** De.ov_source == De.ov_result, origtup is already
  178.                     ** correct.
  179.                     */
  180.  
  181.                     if (De.ov_diffrel)
  182.                     {
  183.                         if (l1 = get(De.ov_result, &De.ov_uptid, &hitid, De.ov_origtup, CURTUP))
  184.                             syserr("interp:get on resdom %s, %d", locv(De.ov_uptid), l1);
  185.                         bmove(De.ov_origtup, De.ov_outtup, De.ov_result->reldum.relwid);
  186.                     }
  187.                     else
  188.                     {
  189.                         bmove(De.ov_intup, De.ov_outtup, De.ov_result->reldum.relwid);
  190.                     }
  191.                 }
  192.             }
  193.         }
  194.         else
  195.         {
  196.             /*
  197.             ** This is really here for the 68k machines,
  198.             ** this works on the VAX, but nowhere else...
  199.              if ( tos->type == INT && tos->len == 1)
  200.                  tos->value.sym_data.i1type = tos->value.sym_data.i2type;
  201.             */
  202.             if (Equel)
  203.                 equelatt(tos);    /* send attribute to equel */
  204.             else
  205.             {
  206.                 if (tos->type == CHAR)
  207.                     s1 = tos->value.sym_data.cptype;
  208.                 else
  209.                     s1 = tos->value.sym_data.c0type;
  210.                 printatt(tos->type, tos->len & I1MASK, s1);    /* print attribute */
  211.             }
  212.         }
  213.         SPOP(tos);
  214.         goto loop;
  215.  
  216.  
  217.       case BOP:
  218.         op2 = (SYMBOL *)SPOP(tos);
  219.         op1 = (SYMBOL *)tos;
  220.         typecheck(op1, op2, opval);
  221.         val1 = &op1->value.sym_data;
  222.         val2 = &op2->value.sym_data;
  223.  
  224.         switch (tos->type)
  225.         {
  226.           case INT:
  227.             switch (tos->len)
  228.             {
  229.               case 1:
  230.                 switch (opval)
  231.                 {
  232.                   case opADD:
  233.                     val1->i1type += val2->i1type;
  234.                     goto loop;
  235.  
  236.                   case opSUB:
  237.                     val1->i1type -= val2->i1type;
  238.                     goto loop;
  239.  
  240.                   case opMUL:
  241.                     val1->i1type *= val2->i1type;
  242.                     goto loop;
  243.  
  244.                   case opDIV:
  245.                     val1->i1type /= val2->i1type;
  246.                     goto loop;
  247.  
  248.                   case opMOD:
  249.                     val1->i1type %= val2->i1type;
  250.                     goto loop;
  251.  
  252.                   case opPOW:
  253.                     itof(op1);
  254.                     itof(op2);
  255.                     val1->f8type = pow(val1->f8type, val2->f8type);
  256.                     goto loop;
  257.  
  258.                   /* relational operator */
  259.                   default:
  260.                     tos->len = 2;
  261.                     if (val1->i1type > val2->i1type)
  262.                         l1 = 1;
  263.                     else
  264.                         if (val1->i1type == val2->i1type)
  265.                             l1 = 0;
  266.                         else
  267.                             l1 = -1;
  268.                     val1->i2type = relop_interp(opval, l1);
  269.                     goto loop;
  270.                 }
  271.               case 2:
  272.                 switch (opval)
  273.                 {
  274.                   case opADD:
  275.                     val1->i2type += val2->i2type;
  276.                     goto loop;
  277.  
  278.                   case opSUB:
  279.                     val1->i2type -= val2->i2type;
  280.                     goto loop;
  281.  
  282.                   case opMUL:
  283.                     val1->i2type *= val2->i2type;
  284.                     goto loop;
  285.  
  286.                   case opDIV:
  287.                     val1->i2type /= val2->i2type;
  288.                     goto loop;
  289.  
  290.                   case opMOD:
  291.                     val1->i2type %= val2->i2type;
  292.                     goto loop;
  293.  
  294.                   case opPOW:
  295.                     itof(op1);
  296.                     itof(op2);
  297.                     val1->f8type = pow(val1->f8type, val2->f8type);
  298.                     goto loop;
  299.  
  300.                   /* relational operator */
  301.                   default:
  302.                     l1 = val1->i2type - val2->i2type;
  303.                     val1->i2type = relop_interp(opval, l1);
  304.                     goto loop;
  305.                 }
  306.  
  307.               case 4:
  308.                 switch(opval)
  309.                 {
  310.                   case opADD:
  311.                     val1->i4type += val2->i4type;
  312.                     goto loop;
  313.  
  314.                   case opSUB:
  315.                     val1->i4type -= val2->i4type;
  316.                     goto loop;
  317.  
  318.                   case opMUL:
  319.                     val1->i4type *= val2->i4type;
  320.                     goto loop;
  321.  
  322.                   case opDIV:
  323.                     val1->i4type /= val2->i4type;
  324.                     goto loop;
  325.  
  326.                   case opMOD:
  327.                     val1->i4type %= val2->i4type;
  328.                     goto loop;
  329.  
  330.                   case opPOW:
  331.                     itof(op1);
  332.                     itof(op2);
  333.                     val1->f8type = pow(val1->f8type, val2->f8type);
  334.                     goto loop;
  335.  
  336.                   /* relational operator */
  337.                   default: 
  338.                     tos->len = 2;
  339.                     if (val1->i4type > val2->i4type)
  340.                         l1 = 1;
  341.                     else
  342.                         if (val1->i4type == val2->i4type)
  343.                             l1 = 0;
  344.                         else
  345.                             l1 = -1;
  346.  
  347.                     val1->i2type = relop_interp(opval, l1);
  348.                     goto loop;
  349.  
  350.                 }
  351.             }
  352.  
  353.           case FLOAT:
  354.             switch (tos->len)
  355.             {
  356.               case 4:
  357.                 switch (opval)
  358.                 {
  359.                   case opADD:
  360.                     val1->f4type += val2->f4type;
  361.                     goto loop;
  362.  
  363.                   case opSUB:
  364.                     val1->f4type -= val2->f4type;
  365.                     goto loop;
  366.  
  367.                   case opMUL:
  368.                     val1->f4type *= val2->f4type;
  369.                     goto loop;
  370.  
  371.                   case opDIV:
  372.                     val1->f4type /= val2->f4type;
  373.                     goto loop;
  374.  
  375.                   case opPOW:
  376.                     val1->f4type = pow(val1->f4type, val2->f4type);
  377.                     goto loop;
  378.  
  379.                   default:
  380.                     tos->type = INT;
  381.                     tos->len = 2;
  382.                     if (val1->f4type > val2->f4type)
  383.                         l1 = 1;
  384.                     else
  385.                         if (val1->f4type == val2->f4type)
  386.                             l1 = 0;
  387.                         else
  388.                             l1 = -1;
  389.                     val1->i2type = relop_interp(opval, l1);
  390.                     goto loop;
  391.                 }
  392.               case 8:
  393.                 switch (opval)
  394.                 {
  395.                   case opADD:
  396.                     val1->f8type += val2->f8type;
  397.                     goto loop;
  398.  
  399.                   case opSUB:
  400.                     val1->f8type -= val2->f8type;
  401.                     goto loop;
  402.  
  403.                   case opMUL:
  404.                     val1->f8type *= val2->f8type;
  405.                     goto loop;
  406.  
  407.                   case opDIV:
  408.                     val1->f8type /= val2->f8type;
  409.                     goto loop;
  410.  
  411.                   case opPOW:
  412.                     val1->f8type = pow(val1->f8type, val2->f8type);
  413.                     goto loop;
  414.  
  415.                   default:
  416.                     tos->type = INT;
  417.                     tos->len = 2;
  418.                     if (val1->f8type > val2->f8type)
  419.                         l1 = 1;
  420.                     else
  421.                         if (val1->f8type == val2->f8type)
  422.                             l1 = 0;
  423.                         else
  424.                             l1 = -1;
  425.                     val1->i2type = relop_interp(opval, l1);
  426.                     goto loop;
  427.                 }
  428.             }
  429.  
  430.         case CHAR:
  431.             switch (opval) 
  432.             {
  433.                 case opSUB:
  434.                     newstring(op1, op2);
  435.                     goto loop;
  436.                 case opADD:
  437.                 case opCONCAT:
  438.                     concatsym(op1, op2);    /* concatenate the two symbols */
  439.                     goto loop;
  440.                 default:
  441.                     l1 = lexcomp(val1->cptype, size(op1), val2->cptype, op2->len & I1MASK,0);
  442.                     tos->type = INT;
  443.                     tos->len = 2;
  444.                     val1->i2type = relop_interp(opval, l1);
  445.                     goto loop;
  446.             }
  447.         }    /* end of BOP */
  448.  
  449.        case UOP:
  450.         val1 = &tos->value.sym_data;
  451.         switch (opval)
  452.         {
  453.            case opMINUS:
  454.            case opABS:
  455.             if (tos->type == CHAR)
  456.                 ov_err(BADUOPC);
  457.             l1 = opval == opMINUS;
  458.             switch (tos->type)
  459.             {
  460.                case INT:
  461.                 switch (tos->len)
  462.                 {
  463.                   case 1:
  464.                     if (l1 || val1->i1type < 0)
  465.                         val1->i1type = -val1->i1type;
  466.                        goto loop;
  467.                   case 2:
  468.                     if (l1 || val1->i2type < 0)
  469.                         val1->i2type = -val1->i2type;
  470.                        goto loop;
  471.  
  472.                   case 4:
  473.                     if (l1 || val1->i4type < 0)
  474.                         val1->i4type = -val1->i4type;
  475.                     goto loop;
  476.                 }
  477.  
  478.               case FLOAT:
  479.                 switch (tos->len)
  480.                 {
  481.                   case 4:
  482.                     if (l1 || val1->f4type < 0.0)
  483.                         val1->f4type = -val1->f4type;
  484.                     goto loop;
  485.                   case 8:
  486.                     if (l1 || val1->f8type < 0.0)
  487.                         val1->f8type = -val1->f8type;
  488.                     goto loop;
  489.                 }
  490.             }
  491.  
  492.           case opNOT:
  493.             val1->i2type = !val1->i2type;
  494.           case opPLUS:
  495.             if (tos->type == CHAR)
  496.                 ov_err(BADUOPC);
  497.             goto loop;
  498.  
  499.           case opASCII:
  500.             ascii(tos);
  501.             goto loop;
  502.  
  503.           case opINT1:
  504.             typecoerce(tos, INT, 1);
  505.             goto loop;
  506.  
  507.           case opINT2:
  508.             typecoerce(tos, INT, 2);
  509.             goto loop;
  510.  
  511.           case opINT4:
  512.             typecoerce(tos, INT, 4);
  513.             goto loop;
  514.  
  515.           case opFLOAT4:
  516.             typecoerce(tos, FLOAT, 4);
  517.             goto loop;
  518.  
  519.           case opFLOAT8:
  520.             typecoerce(tos, FLOAT, 8);
  521.             goto loop;
  522.  
  523.           default:
  524.             if (tos->type == CHAR)
  525.                 ov_err(BADUOPC);
  526.             if (tos->type == INT)
  527.                 itof(tos);
  528.             if (tos->len == 4)
  529.             {
  530.                 val1->f8type = val1->f4type;
  531.                 tos->len = 8;
  532.             }
  533.             switch (opval)
  534.             {
  535.               case opATAN:
  536.                 val1->f8type = atan(val1->f8type);
  537.                 goto loop;
  538.     
  539.               case opLOG:
  540.                 val1->f8type = log(val1->f8type);
  541.                 goto loop;
  542.     
  543.               case opSIN:
  544.                 val1->f8type = sin(val1->f8type);
  545.                 goto loop;
  546.  
  547.               case opCOS:
  548.                 val1->f8type = cos(val1->f8type);
  549.                 goto loop;
  550.  
  551.               case opSQRT:
  552.                 val1->f8type = sqrt(val1->f8type);
  553.                 goto loop;
  554.  
  555.               case opEXP:
  556.                 val1->f8type = exp(val1->f8type);
  557.                 goto loop;
  558.  
  559.               default:
  560.                 syserr("interp:bad uop %d",opval);
  561.             }
  562.         }
  563.  
  564.  
  565.        case AOP:
  566.         aop_interp(opval, tos);
  567.         SPOP(tos);        /* pop this symbol */
  568.         goto loop;
  569.  
  570.     }
  571.     syserr("interp: fell out");
  572.     /*NOTREACHED*/
  573. }
  574. /*
  575. **    relop_interp interprets the relational operators
  576. **    (ie. EQ, NE etc.) and returns true or false
  577. **    by evaluating l1.
  578. **
  579. **    l1 should be greater than, equal or less than zero.
  580. */
  581.  
  582. relop_interp(opval, l1)
  583. int    opval;
  584. int    l1;
  585. {
  586.     register int    i;
  587.  
  588.     i = l1;
  589.  
  590.     switch (opval)
  591.     {
  592.  
  593.       case opEQ:
  594.         return (i == 0);
  595.  
  596.       case opNE:
  597.         return (i != 0);
  598.  
  599.       case opLT:
  600.         return (i < 0);
  601.  
  602.       case opLE:
  603.         return (i <= 0);
  604.  
  605.       case opGT:
  606.         return (i > 0);
  607.  
  608.       case opGE:
  609.         return (i >= 0);
  610.  
  611.       default:
  612.         syserr("relop:bad relop or bop %d", opval);
  613.     }
  614.     /*NOTREACHED*/
  615. }
  616. /*
  617. **    Aggregate values are stored in De.ov_outtup. De.ov_tend points
  618. **    to the spot for the next aggregate. Aop_interp()
  619. **    computes the value for the aggregate and leaves
  620. **    the result in the position pointed to by De.ov_tend.
  621. */
  622.  
  623. aop_interp(opval, tos)
  624. int        opval;
  625. register SYMBOL    *tos;
  626. {
  627.     register int    i;
  628.     int        l1;
  629.     ANYTYPE        numb;    /* used for type conversion */
  630.  
  631. #ifndef    VAX
  632.     l1 = (tos->type != CHAR);
  633.     switch (opval) {
  634.     case opCOUNT:
  635.     case opCOUNTU:
  636.       i = 4;
  637.       l1 = 1;
  638.       break;
  639.     case opANY:
  640.       i = 2;
  641.       l1 = 1;
  642.       break;
  643.     case opAVG:
  644.     case opAVGU:
  645.       i = 8;
  646.       break;
  647.     default:
  648.       i = tos->len;
  649.     }
  650.     if (l1)
  651.     {
  652.         l1 = De.ov_tend - De.ov_outtup;
  653.         De.ov_tend = De.ov_outtup + ((l1 - 1)|(i-1))+1;
  654.     }
  655. #endif
  656.     bmove(De.ov_tend, (char *) &numb, 8);    /* note: this assumes that
  657.                 there are always 8 bytes which can be moved.
  658.                 ** if it moves beyond De.ov_tend, it's ok */
  659.     switch (opval)
  660.     {
  661.  
  662.       case opSUMU:
  663.       case opSUM:
  664.         if (*De.ov_counter <= 1)
  665.             goto puta;
  666.         switch (tos->type)
  667.         {
  668.           case INT:
  669.             switch(tos->len)
  670.             {
  671.               case 1:
  672.                 tos->value.sym_data.i1type += numb.i1type;
  673.                 goto puta;
  674.  
  675.               case 2:
  676.                 tos->value.sym_data.i2type += numb.i2type;
  677.                 goto puta;
  678.  
  679.               case 4:
  680.                 tos->value.sym_data.i4type += numb.i4type;
  681.                 goto puta;
  682.             }
  683.  
  684.           case FLOAT:
  685.             if (tos->len == 4)
  686.                 tos->value.sym_data.f4type += numb.f4type;
  687.             else
  688.                 tos->value.sym_data.f8type += numb.f8type;
  689.             goto puta;
  690.  
  691.           default:
  692.             ov_err(BADSUMC);    /* cant sum char fields */
  693.         }
  694.  
  695.       case opCOUNTU:
  696.       case opCOUNT:
  697.         tos->type = CNTTYPE;
  698.         tos->len = CNTLEN;
  699.         tos->value.sym_data.i4type = *De.ov_counter;
  700.         goto puta;
  701.  
  702.       case opANY:
  703.         tos->type = OANYTYPE;
  704.         tos->len = OANYLEN;
  705.         if (*De.ov_counter)
  706.         {
  707.             tos->value.sym_data.i2type = 1;
  708.             if (!De.ov_bylist && (De.ov_agcount == 1))
  709.                 De.ov_targvc = 0;    /* if simple agg. stop scan */
  710.         }
  711.         else
  712.             tos->value.sym_data.i2type = 0;
  713.         goto puta;
  714.  
  715.       case opMIN:
  716.       case opMAX:
  717.         if (*De.ov_counter<=1)
  718.             goto puta;
  719.         switch (tos->type)
  720.         {
  721.           case INT:
  722.             switch (tos->len)
  723.             {
  724.               case 1:
  725.                 i = (tos->value.sym_data.i1type < numb.i1type);
  726.                 break;
  727.  
  728.               case 2:
  729.                 i = (tos->value.sym_data.i2type < numb.i2type);
  730.                 break;
  731.  
  732.               case 4:
  733.                 i = (tos->value.sym_data.i4type < numb.i4type);
  734.                 break;
  735.             }
  736.             break;
  737.  
  738.           case FLOAT:
  739.             if (tos->len == 4)
  740.                 i = (tos->value.sym_data.f4type < numb.f4type);
  741.             else
  742.                 i = (tos->value.sym_data.f8type < numb.f8type);
  743.             break;
  744.  
  745.           case CHAR:
  746.             l1 = size(tos);
  747.             i = (lexcomp(tos->value.sym_data.cptype, l1, De.ov_tend, l1,0) < 0);
  748.             break;
  749.  
  750.           default:    
  751.             syserr("interp:bad op type for opMIN/MAX %d", tos->type);
  752.         }
  753.  
  754.         /* check result of comparison */
  755.         if (opval == opMAX)
  756.             i = !i;    /* complement test for opMAX */
  757.         if (i)
  758.             goto puta;    /* condition true. new value */
  759.  
  760.         /* condition false. Keep old value */
  761.         goto done;
  762.  
  763.  
  764.       case opAVGU:
  765.       case opAVG:
  766.         if (tos->type == INT)
  767.             itof(tos);
  768.         else
  769.             if (tos->type == CHAR)
  770.                 ov_err(BADAVG);
  771.         if (tos->len == 4)
  772.         {
  773.             tos->value.sym_data.f8type = tos->value.sym_data.f4type;
  774.         /*    tos->len = 8; */
  775.         }
  776.         if (*De.ov_counter > 1)
  777.         {
  778.             tos->value.sym_data.f8type = numb.f8type + (tos->value.sym_data.f8type - numb.f8type) / *De.ov_counter;
  779.         }
  780.         tos->len = 8;
  781.         goto puta;
  782.  
  783.       default:
  784.         syserr("interp:bad agg op %d", tos->type);
  785.     }
  786.  
  787. puta:
  788.     tout(tos, De.ov_tend, tos->len);
  789. done:
  790.     De.ov_tend += tos->len & I1MASK;
  791. }
  792.